package com.chl.deepmind;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 *
 * @author 陈宏亮
 */
public class SimpleDeep {

    public double[] weights;
    public Random random = new Random();
    public double move = 1;
    public int batchSize = 50000;
    public double rate = 0.01;

    public SimpleDeep() {
        weights = new double[3];
        for (int i = 0; i < 3; i++) {
            weights[i] = 1 - random.nextDouble() - random.nextDouble();
        }
    }

    public Map<String, Object> getTrainData(int n) {
        Map<String, Object> trainData = new HashMap<String, Object>();
        double[][] data = new double[n][3];
        int[] target = new int[n];
        int x, y;
        for (int i = 0; i < n; i++) {
            x = random.nextInt(400);
            y = random.nextInt(400);
            data[i][0] = x;
            data[i][1] = y;
            data[i][2] = move;
            target[i] = (y > 200 ? 1 : -1);
        }
        trainData.put("target", target);
        trainData.put("data", data);
        return trainData;
    }

    // 分类模型，根据这个模型来动态调整权重W的值
    public int reduce(double[] in) {
        double sum = 0;
        for (int i = 0; i < weights.length; i++) {
            sum = sum + in[i] * weights[i];
        }
        return sum > 0 ? 1 : -1;
    }

    // 学习算法
    public void stady(double[] in, int target) {
        int out = reduce(in);
        int error = target - out;
        for (int i = 0; i < weights.length; i++) {
            weights[i] = weights[i] + rate * error * in[i];
        }
    }

    // 学习一批长度
    public void train() {
        Map<String, Object> trainData;
        for (int i = 0; i < 10000; i++) {
            trainData = getTrainData(batchSize);
            int[] target = (int[]) trainData.get("target");
            double[][] data = (double[][]) trainData.get("data");
            for (int j = 0; j < batchSize; j++) {
                stady(data[j], target[j]);
            }

            if ((i + 1) % 20 == 0) {
                Object[] res = test();
                System.out.println(res[0] + ",[" + weights[0] + ", " + weights[1] + ", " + weights[2] + "]");
                if ((double) res[0] == 1) {
                    break;
                }
            }
        }
    }

    public Object[] test() {
        double suc = 0;
        List<double[]> sucList = new ArrayList<double[]>();
        List<double[]> errList = new ArrayList<double[]>();
        Map<String, Object> trainData = getTrainData(batchSize);
        int[] target = (int[]) trainData.get("target");
        double[][] data = (double[][]) trainData.get("data");
        for (int i = 0; i < batchSize; i++) {
            if (reduce(data[i]) == target[i]) {
                suc++;
                sucList.add(data[i]);
            } else {
                errList.add(data[i]);
            }
        }
        return new Object[]{suc / batchSize, sucList.toArray(new double[][]{}), errList.toArray(new double[][]{})};
    }

    public static void main(String[] args) {
        SimpleDeep deep = new SimpleDeep();
        deep.train();
    }
}
